package com.xlx.ui.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import com.xlx.ui.domain.MO.File;
import com.xlx.ui.domain.VO.ResultBody;
import com.xlx.ui.mapper.FileMapper;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.Sqls;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: 张川
 * @date: 2020-12-13 18:00
 */
@Api(tags = "文件资源")
@Service
@Slf4j
public class FileService {

    @Autowired
    private FileMapper fileMapper;

    String bucketName = "xue-dist";
    String endpoint = "oss-cn-chengdu.aliyuncs.com";
    String accessKeyId = "LTAI4G1QbP3udPyKBpGDMxXa";
    String accessKeySecret = "RXPN5BI6yMKbKDyDeolJU2q4JkaAMZ";

    private OSS getOss() {
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setMaxConnections(200);
        conf.setSocketTimeout(10000);
        conf.setConnectionTimeout(10000);
        conf.setConnectionRequestTimeout(1000);
        conf.setIdleConnectionTime(10000);
        conf.setMaxErrorRetry(5);
        conf.setSupportCname(true);
        conf.setRedirectEnable(true);
        conf.setVerifySSLEnable(true);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
        return ossClient;
    }

    public ArrayList<Object> getFileList(String dir) {
        ArrayList<Object> list = new ArrayList<>();
        String[] path = dir.split("/");
        OSS ossClient = getOss();
        String KeyPrefix = dir;
        ObjectListing objectListing;
        List<File> fileList;
        if (path.length == 0) {
            fileList = fileMapper.selectAll();
            objectListing = ossClient.listObjects(bucketName);
        } else {
            fileList = fileMapper.selectByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("name", path[0])).build());
            objectListing = ossClient.listObjects(bucketName, KeyPrefix);
            fileList = fileList.stream().filter(file1 -> !file1.getPath().equals("/" + file1.getName())).collect(Collectors.toList());
        }

        objectListing.setDelimiter("/");
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        if (sums.size() > 0 && path.length != 0) {
            sums.remove(0);
        }
        ossClient.shutdown();
        list.add(sums);
        list.add(fileList);
        return list;
    }

    /**
     * 获取文件列表
     */
    public List<JSONObject> list(String dir) {
        ArrayList<Object> fileList = getFileList(dir);
        List<OSSObjectSummary> sums = (List<OSSObjectSummary>) fileList.get(0);
        List<File> fileName = (List<File>) fileList.get(1);
        List<JSONObject> objects = new ArrayList<>();
        for (OSSObjectSummary ossObjectSummary : sums) {
            String key = StrUtil.removePrefix(ossObjectSummary.getKey(), dir);
            if (key.split("/").length <= 1) {
                String[] split = ossObjectSummary.getKey().split("/");
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("title", ossObjectSummary.getKey().replace(dir, "").replace("/", ""));
                if (split[split.length - 1].contains(".")) {
                    String title = split[split.length - 1];
                    String[] split1 = StrUtil.split(title, ".");
                    jsonObject.put("wjname", split1[0]);
                    jsonObject.put("type", split1[1]);
                    jsonObject.put("imgtype", this.uotype(split1[1]));
                    jsonObject.put("size", ossObjectSummary.getSize());
                } else {
                    jsonObject.put("wjname", ossObjectSummary.getKey().replace(dir, "").replace("/", ""));
                    jsonObject.put("type", "文件夹");
                    jsonObject.put("imgtype", "wjj");
                    jsonObject.put("size", 0);
                }
                jsonObject.put("lastModified", ossObjectSummary.getLastModified());
                jsonObject.put("name", ossObjectSummary.getKey());
                jsonObject.put("state", file_filter(fileName, ossObjectSummary.getKey()));
                objects.add(jsonObject);
            }
        }


        return objects;
    }

    /**
     * 搜索文件
     *
     * @param dir
     * @param fileName
     * @return
     */
    public List<JSONObject> search(String dir, String fileName) {
        List<JSONObject> list = list(dir);
        List<JSONObject> fileList = new ArrayList<>();
        for (JSONObject file : list) {
            if (file.getString("name").contains(fileName)) {
                fileList.add(file);
            }
        }
        return fileList;
    }


    public String uotype(String item) {
        String type;
        switch (item) {
            case "jpg":
            case "gif":
            case "jpeg":
            case "svg":
            case "png": // 图片类型
                type = "tp";
                break;
            case "txt":// txt类型
                type = "txt";
                break;
            case "dox":
            case "docx":
            case "pot":
            case "ppt":
            case "potx":
            case "xls":
            case "csv":// world
                type = "wd";
                break;
            case "rar":
            case "zip":
            case "arj":
            case "tar":// 压缩文件
                type = "ysb";
                break;
            default:
                type = "mr";
        }
        return type;
    }

    /**
     * 创建文件夹
     *
     * @param dir
     * @param name
     * @return
     */
    public boolean creat(String dir, String name) {
        OSS ossClient = getOss();
        String content = "Hello OSS";
        if (dir.startsWith("/")) {
            dir = dir.substring(1);
        }
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, dir + name + "/", new ByteArrayInputStream(content.getBytes()));
        try {
            ossClient.putObject(putObjectRequest);
            String[] paths = dir.split("/");
//            this.addExamine(paths[0], dir, name + "/",1);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 删除文件
     *
     * @param dir
     * @return
     */
    public boolean delete(String dir) {
        OSS client = getOss();
        try {
            ObjectListing objectListing = client.listObjects(bucketName, dir);
            objectListing.setDelimiter("/");
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            client.deleteObject(bucketName, dir);
            fileMapper.deleteByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("key", dir)).build());
            sums.remove(0);
            for (int i = 0; i < sums.size(); i++) {
                client.deleteObject(bucketName, sums.get(i).getKey());
                fileMapper.deleteByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("key", sums.get(i).getKey())).build());
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        } finally {
            client.shutdown();
        }
    }

    /**
     * 上传文件
     *
     * @param dir
     * @return
     */
    public JSONObject upload(String dir) {
        try {
            JSONObject data = new JSONObject();
            OSS ossClient = getOss();
            data.put("OSSAccessKeyId", accessKeyId);
            data.put("host", "xue-dist.oss-cn-chengdu.aliyuncs.com");
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            data.put("policy", encodedPolicy);
            data.put("signature", postSignature);
            String end = String.valueOf(expireEndTime / 1000);
            data.put("key", dir + end);
            data.put("saveName", end);
            data.put("startsWith", dir);
            return data;
        } catch (UnsupportedEncodingException e) {
            log.error("生成签名失败:{}", e.getMessage());
            return null;
        }

    }

    /**
     * 下载文件
     *
     * @param name
     * @param title
     * @return
     */
    public String down(String name, String title) {
        OSS client = getOss();
        // 设置URL过期时间为1小时
        Date expiration = new Date(new Date().getTime() + 3600 * 10000);
        // 生成URL
        URL url = client.generatePresignedUrl(bucketName, name, expiration);
        return url.toString();
    }

    /**
     * 文件预览
     *
     * @param fileName
     * @return
     */
    public String preview(String fileName) {
        OSS client = getOss();
        // 设置URL过期时间为1小时
        Date expiration = new Date(new Date().getTime() + 3600 * 10000);
        // 生成URL
        URL url = client.generatePresignedUrl(bucketName, fileName, expiration);
        return url.toString();
    }

    /**
     * 拷贝文件
     *
     * @param moveFile
     * @param baseFile
     * @return
     */
    public boolean move(String moveFile, String baseFile) {
        OSS client = getOss();
        String[] file_names = moveFile.split("/");
        String file_name = moveFile.endsWith("/") ? file_names[file_names.length - 1] + "/" : file_names[file_names.length - 1];
        try {
            ObjectListing objectListing = client.listObjects(bucketName, moveFile);
            objectListing.setDelimiter("/");
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
            client.copyObject(bucketName, moveFile, bucketName, baseFile + file_name);
            client.deleteObject(bucketName, moveFile);
            fileMapper.deleteByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("key", moveFile)).build());
            this.addExamine(null, baseFile, file_name,1);
            sums.remove(0);
            moveFile = StrUtil.removeSuffix(moveFile, file_name);
            for (int i = 0; i < sums.size(); i++) {
                file_name = StrUtil.removePrefix(sums.get(i).getKey(), moveFile);
                client.copyObject(bucketName, sums.get(i).getKey(), bucketName, baseFile + file_name);
                client.deleteObject(bucketName, sums.get(i).getKey());
                fileMapper.deleteByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("key", sums.get(i).getKey())).build());
                this.addExamine(null, baseFile, file_name,1);
            }
            return true;
        } catch (Exception e) {
            log.error("拷贝文件异常:{}", e.getMessage());
            return false;
        } finally {
            client.shutdown();
        }
    }

    //添加审核文件
    public ResultBody addExamine(String user, String path, String file_name,Integer examine) {
        if (StrUtil.isBlank(user)) {
            String[] split = path.split("/");
            user = split[0];
            if (StrUtil.isBlank(user)) {
                split = file_name.split("/");
                user = split[0];
                examine = 1;
                path = "/";
            }
        }
        int countByExample = fileMapper.selectCountByExample(Example.builder(File.class).where(Sqls.custom().andEqualTo("name", user)).build());
        if (countByExample < 1) {
            OSS ossClient = getOss();
            String content = "Hello OSS";
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, user + "/", new ByteArrayInputStream(content.getBytes()));
            try {
                ossClient.putObject(putObjectRequest);
            } catch (Exception e) {
                log.error(e.getMessage());
            } finally {
                ossClient.shutdown();
            }
            File file = File.builder().createTime(DateUtil.now()).examine(1).name(user).path("/" ).fileName(user).key(user+"/").build();
            fileMapper.insertSelective(file);
        }
        File file = new File();
        file.setExamine(examine);
        file.setName(user);
        file.setPath(path);
        file.setFileName(file_name);
        file.setCreateTime(DateUtil.now());
        file.setKey(path + file_name);
        fileMapper.insertSelective(file);
        return ResultBody.success();
    }


    /**
     * 获取文件状态
     *
     * @param files
     * @param name
     * @return 0:等待审核,1:审核通过,2:审核未通过,3:未知
     */
    public Integer file_filter(List<File> files, String name) {
        Integer state = 3;
        if(name.endsWith("/")){
            return 1;
        }
        for (File file : files) {

            if (name.equals(file.getKey())) {
                state = file.getExamine();
                if(file.getPath().equals("/")){
                    state = 1;
                    break;
                }
                break;
            }
        }
        return state;
    }

    public List<File> getExamine(Integer page, Integer limit, String name, String fileName) {
        File file = new File();
        if (StrUtil.isNotBlank(name)) {
            file.setName(name);
        }
        if (StrUtil.isNotBlank(fileName)) {
            file.setFileName(fileName);
        }
        List<File> fileList = fileMapper.selectByRowBounds(file, new RowBounds(page - 1, limit));
        fileList = fileList.stream().filter(file1 -> !file1.getPath().equals("/")).collect(Collectors.toList());
        return fileList;
    }


    public boolean update(File file) {
        fileMapper.updateByPrimaryKeySelective(file);
        return true;
    }

}
